# -*- coding: utf-8 -*-

from osv import fields,osv
from osv.orm import browse_record
import tools
from functools import partial
import pytz
import pooler
from tools.translate import _
from service import security
import netsvc

general_state = (
    ('draft', 'Draft'),
    ('confirmed', 'Confirmed'),
    ('approved', 'Approved'),
)

class aas_academic_year(osv.osv):
    def default_seq(self, cr, uid, context=False):
        res = 0
        sql = '''
            SELECT MAX(COALESCE(seq, 0)) as max
            FROM aas_academic_year
        '''
        cr.execute(sql)
        if cr.rowcount > 0:
            max = cr.fetchone()[0]
            print max
            try:
                res = int(max) + 1
            except: pass
        return res
    _name = 'aas.academic.year'
    _description = 'Năm học'
    _columns = {
        'name': fields.char('Tên năm học', size=64, required=True, help='Ví dụ: 2010-2011'),
        'code': fields.char('Mã năm học', size=64, help='Ví dụ: C'),
        'date_start': fields.date('Ngày bắt đầu', readonly=True, help='Là ngày bắt đầu của tuần học đầu tiên của năm học này.'),
        'date_end': fields.date('Ngày kết thúc', readonly=True, help='Là ngày kết thúc của tuần học cuối cùng của năm học này.'),
        'academic_semesters': fields.one2many('aas.academic.semester', 'academic_year', string='Các học kỳ của năm học này'),
        'academic_weeks': fields.one2many('aas.academic.week', 'academic_year', string='Các tuần học của năm học này', readonly=True),
        'seq': fields.integer('Thứ tự', required=True),
    }
    _sql_constraints = [
#        ('name_uniq', 'UNIQUE(name)', 'The name of the academic year must be unique!'),
#        ('code_uniq', 'UNIQUE(code)', 'The code of the academic year must be unique!'),
    ]
    _defaults = {
        'seq': default_seq,
    }
    _order = 'seq'
    
    def copy(self, cr, uid, id, default=None, context=None):
        if not default:
            default = {}
        year = self.browse(cr, uid, id, context=context)
        default.update({
            'name': year.name + ' (copied)',
            'code': year.code + ' (copied)',
            'date_start': False,
            'date_end': False,
            'academic_semesters': [],
        })
        return super(aas_academic_year, self).copy(cr, uid, id, default, context)
    
    def get_current_academic_state(self, cr, uid, context=None):
        result = [False, False, False]
        year_str = '-1'
        semester_str = '-1'
        week_str = '-1'
        sql = '''
            SELECT value
            FROM trobz_property
            WHERE name = 'ID của năm học hiện tại'
        '''
        cr.execute(sql)
        if cr.rowcount > 0: year_str = cr.fetchone()[0]
        sql = '''
            SELECT value
            FROM trobz_property
            WHERE name = 'ID của học kỳ hiện tại'
        '''
        cr.execute(sql)
        if cr.rowcount > 0: semester_str = cr.fetchone()[0]
        sql = '''
            SELECT value
            FROM trobz_property
            WHERE name = 'ID của tuần học hiện tại'
        '''
        cr.execute(sql)
        if cr.rowcount > 0: week_str = cr.fetchone()[0]
        
        try:
            year_id = int(year_str)
            if year_id > 0: result[0] = self.browse(cr, uid, year_id, context=context)
        except: pass
        
        try:
            semester_id = int(semester_str)
            if semester_id > 0: 
                semester_obj = self.pool.get('aas.academic.semester')
                result[1] = semester_obj.browse(cr, uid, semester_id, context=context)
        except: pass
        
        try:
            week_id = int(week_str)
            if week_id > 0: 
                week_obj = self.pool.get('aas.academic.week')
                result[2] = week_obj.browse(cr, uid, week_id, context=context)
        except: pass
        
        return result
    
    def set_current_academic_state(self, cr, uid, year_id, semester_id, week_id, context=None):
        sql = '''
            SELECT 1
            FROM aas_academic_semester
            WHERE id = %s AND academic_year != %s 
        '''
        cr.execute(sql, (semester_id, year_id))
        if cr.rowcount > 0:
            raise osv.except_osv(_('Lỗi!'), _('Học kỳ không nằm trong năm học!'))
        sql = '''
            SELECT 1
            FROM aas_academic_week
            WHERE id = %s AND academic_semester != %s 
        '''
        cr.execute(sql, (week_id, semester_id))
        if cr.rowcount > 0:
            raise osv.except_osv(_('Lỗi!'), _('Tuần học không nằm trong học kỳ!'))    
        property_obj = self.pool.get('trobz.property')
        sql = '''
            SELECT id
            FROM trobz_property
            WHERE name = 'ID của năm học hiện tại'
        '''
        cr.execute(sql)
        if cr.rowcount > 0: 
            year_property_id = cr.fetchone()[0]
            property_obj.write(cr, 1, [year_property_id], {'value': str(year_id)}, context=context)
        sql = '''
            SELECT id
            FROM trobz_property
            WHERE name = 'ID của học kỳ hiện tại'
        '''
        cr.execute(sql)
        if cr.rowcount > 0: 
            semester_property_id = cr.fetchone()[0]
            property_obj.write(cr, 1, [semester_property_id], {'value': str(semester_id)}, context=context)
        sql = '''
            SELECT id
            FROM trobz_property
            WHERE name = 'ID của tuần học hiện tại'
        '''
        cr.execute(sql)
        if cr.rowcount > 0: 
            week_property_id = cr.fetchone()[0]
            property_obj.write(cr, 1, [week_property_id], {'value': str(week_id)}, context=context)
        return True
    
    def get_view_id(self, cr, uid, module, view_xml_id, context=None):
        data_obj = self.pool.get('ir.model.data')
        data = data_obj._get_id(cr, uid, module, view_xml_id)
        view_id = data_obj.browse(cr, uid, data).res_id
        return view_id
    
aas_academic_year()

class aas_academic_semester(osv.osv):
    _name = 'aas.academic.semester'
    _description = 'Học kỳ'
    _columns = {
        'name': fields.char('Tên học kỳ', size=64),
        'number': fields.integer('Số thứ tự học kỳ', required=True, help='Ví dụ: 1'),
        'academic_year': fields.many2one('aas.academic.year', string='Năm học', required=True, help='Năm học chứa học kỳ này.'),
        'date_start': fields.date('Ngày bắt đầu', readonly=True, help='Là ngày bắt đầu của tuần học đầu tiên của học kỳ này.'),
        'date_end': fields.date('Ngày kết thúc', readonly=True, help='Là ngày kết thúc của tuần học cuối cùng của học kỳ này.'),
        'academic_weeks': fields.one2many('aas.academic.week', 'academic_semester', string='Các tuần học của học kỳ này'),
    }
    _sql_constraints = [
#        ('name_academic_year_uniq', 'UNIQUE(name, academic_year)', 'Cannot have more than one semester with the same name in an academic year!'),
    ]
    _order = 'number'
    _defaults = {
        'number': lambda *a: 1,
    }
    
    def write(self, cr, uid, ids, vals, context=False):
        if vals.has_key('number'):
            vals.update({'name': str(vals['number'])})
        return super(aas_academic_semester, self).write(cr, uid, ids, vals, context=context)
    
    def create(self, cr, uid, vals, context=False):
        if vals.has_key('number'):
            vals.update({'name': str(vals['number'])})
        if vals.has_key('number') and vals.has_key('academic_year'):
            existing = self.search(cr, uid, [('number', '=', vals['number']), ('academic_year', '=', vals['academic_year'])], context=context)
            if existing:
                raise osv.except_osv(_('Thông báo!'), _('Đã tồn tại học kỳ có số thứ tự %s trong năm học này!') % (vals['number'],))
        return super(aas_academic_semester, self).create(cr, uid, vals, context=context)
    
    def search(self, cr, uid, args, offset=0, limit=None, order=None, context=None, count=False):
        if not args:
            args = []
        if not context:
            context = {}
        if context.has_key('filter_on_year'):
            year_id = context['filter_on_year']
            if year_id: args.append(('academic_year', '=', year_id))
            else: return []
        return super(aas_academic_semester, self).search(cr, uid, args, limit=limit, order=order, context=context, count=count)
    
    def name_get(self, cr, uid, ids, context=None):
        res = []
        for semester in self.browse(cr, uid, ids, context=context):
            res.append((semester.id, semester.name + ' (' + semester.academic_year.name + ')'))
        return res
    
    def copy(self, cr, uid, id, default=None, context=None):
        if not default:
            default = {}
        semester = self.browse(cr, uid, id, context=context)
        default.update({
            'name': semester.name + ' (copied)',
            'academic_year': semester.academic_year.id,
            'date_start': False,
            'date_end': False,
            'academic_weeks': [],
        })
        return super(aas_academic_semester, self).copy(cr, uid, id, default, context)
    
aas_academic_semester()

class aas_academic_week(osv.osv):
    def onchange_year(self, cr, uid, ids, year, semester):
        res = {'value': {}}
        year_obj = self.pool.get('aas.academic.year')
        semester_obj = self.pool.get('aas.academic.semester')
        if not year: res['value'].update({'academic_semester': False})
        else:
            if semester:
                sql = '''
                    SELECT 1
                    FROM aas_academic_year aay JOIN aas_academic_semester aas ON aay.id = aas.academic_year
                    WHERE aay.id = %s AND aas.id = %s
                '''
                cr.execute(sql, (year, semester))
                if cr.rowcount == 0: res['value'].update({'academic_semester': False}) 
        return res
    
    
    _name = 'aas.academic.week'
    _description = 'Tuần học'
    _columns = {
        'name': fields.char('Tên tuần học', size=64, required=True),
        'number': fields.integer('Số thứ tự tuần học', required=True),
        'academic_semester': fields.many2one('aas.academic.semester', string='Học kỳ', required=True, help='Học kỳ chứa tuần học này.'),
        'academic_year': fields.many2one('aas.academic.year', string='Năm học', required=True, help='Năm học chứa tuần học này.'),
        'date_start': fields.date('Ngày bắt đầu'),
        'date_end': fields.date('Ngày kết thúc'),
    }
    _sql_constraints = [
#        ('name_academic_semester_uniq', 'UNIQUE(name, academic_semester)', 'Cannot have more than one week with the same number in a semester!'),
#        ('number_academic_semester_uniq', 'UNIQUE(number, academic_semester)', 'Cannot have more than one week with the same number in a semester!'),
    ]
    
    def name_get(self, cr, uid, ids, context=None):
        res = []
        for week in self.browse(cr, uid, ids, context=context):
            res.append((week.id, week.name + ' (HK ' + week.academic_semester.name + ' / ' + week.academic_semester.academic_year.name + ')'))
        return res
    
    def write(self, cr, uid, ids, vals, context=None):
        if vals.has_key('number'):
            if vals['number'] < 0:
                raise osv.except_osv(_('Lỗi!'), _('Số thứ tự của tuần học phải lớn hơn 0!'))
        return super(aas_academic_week, self).write(cr, uid, ids, vals, context=context)
    
    def create(self, cr, uid, vals, context=None):
        if vals.has_key('number'):
            semester_obj = self.pool.get('aas.academic.semester')
            if vals['number'] < 0:
                raise osv.except_osv(_('Lỗi!'), _('Số thứ tự của tuần học phải lớn hơn 0!'))
            if vals.has_key('academic_semester'):
                semester = semester_obj.browse(cr, uid, vals['academic_semester'], context=context)
                sql = '''
                    SELECT 1
                    FROM aas_academic_week
                    WHERE number = %s AND academic_semester IN (
                        SELECT id
                        FROM aas_academic_semester
                        WHERE academic_year = %s
                    )
                '''
                cr.execute(sql, (vals['number'], semester.academic_year.id))
                if cr.rowcount > 0:
                    raise osv.except_osv(_('Lỗi!'), _('Một năm học không thể có 2 tuần học có cùng một số thứ tự!'))
        return super(aas_academic_week, self).create(cr, uid, vals, context=context)
aas_academic_week()


class aas_user(osv.osv):
    
    def function_current_academic_state(self, cr, uid, ids, fields, args, context=False):
        res = {}
        year_obj = self.pool.get('aas.academic.year')
        cur_state = year_obj.get_current_academic_state(cr, uid, context=context)
        year = cur_state[0] and cur_state[0].name or '???'
        semester = cur_state[1] and cur_state[1].name or '???'
        week = cur_state[2] and cur_state[2].number or '???'
        print year, semester, week 
        string = ' (Tuần ' + str(week) + ', Học kỳ ' + str(semester) + ', Năm học ' + str(year) + ')'
        for id in ids:
            res[id] = string 
        return res
    
    _inherit = 'res.users'
    _columns = {
        'current_academic_state': fields.function(function_current_academic_state, method=True, type='char', size=64),
    }
aas_user()


class aas_academic_degree(osv.osv):
    _name = 'aas.academic.degree'
    _description= 'Bậc đào tạo'
    _columns = {
        'name': fields.char('Tên bậc đào tạo', size=64, required=True, help='Ví dụ: Đại học'),
    }
    _sql_constraints = [
#        ('name_uniq', 'UNIQUE(name)', 'The name of an academic degree must be unique!'),
    ]
aas_academic_degree()

class aas_academic_type(osv.osv):
    _name = 'aas.academic.type'
    _description= 'Loại hình đào tạo'
    _columns = {
        'name': fields.char('Tên loại hình đào tạo', size=64, required=True, help='Ví dụ: Chính quy'),
    }
    _sql_constraints = [
#        ('name_uniq', 'UNIQUE(name)', 'The name of an academic type must be unique!'),
    ]
aas_academic_type()

class aas_academic_title(osv.osv):
    _name = 'aas.academic.title'
    _description = 'Học vị'
    _columns = {
        'name': fields.char('Tên học vị', size=64, required=True, help='Ví dụ: Tiến sỹ'),
    }
    _sql_constraints = [
#        ('name_uniq', 'UNIQUE(name)', 'The name of the academic title must be unique!'),
    ]
    
    def copy(self, cr, uid, id, default=None, context=None):
        if not default:
            default = {}
        title = self.browse(cr, uid, id, context=context)
        default.update({
            'name': title.name + ' (copied)',
        })
        return super(aas_academic_title, self).copy(cr, uid, id, default, context)
    
aas_academic_title()

class aas_academic_rank(osv.osv):
    _name = 'aas.academic.rank'
    _description = 'Học hàm'
    _columns = {
        'name': fields.char('Tên học hàm', size=64, required=True, help='Ví dụ: Giáo sư'),
    }
    _sql_constraints = [
#        ('name_uniq', 'UNIQUE(name)', 'The name of the academic rank must be unique!'),
    ]
    
    def copy(self, cr, uid, id, default=None, context=None):
        if not default:
            default = {}
        rank = self.browse(cr, uid, id, context=context)
        default.update({
            'name': rank.name + ' (copied)',
        })
        return super(aas_academic_rank, self).copy(cr, uid, id, default, context)
    
aas_academic_rank()

class aas_academic_session(osv.osv):
    def get_sessions_str(self, cr, uid, ids, context=None):
        sessions_str = ''
        sessions_ids = self.search(cr, uid, [('id', 'in', ids)], context=context)
        if sessions_ids:
            sessions_names = []
            for session in self.browse(cr, uid, sessions_ids, context=context):
                sessions_names.append(session.name)
            sessions_str = ', '.join(sessions_names)
        return sessions_str
    
    _name = 'aas.academic.session'
    _description= 'Khóa'
    _columns = {
        'name': fields.char('Tên khóa', size=64, required=True),
        'academic_degree': fields.many2one('aas.academic.degree', string='Bậc đào tạo', required=True),
        'academic_type': fields.many2one('aas.academic.type', string='Loại hình đào tạo', required=True),
        'date_start': fields.date('Date Start'),
        'date_end': fields.date('Date End'),
        'seq': fields.integer('Thứ tự sắp xếp', help='Được dùng để xếp thứ tự trong kế hoạch đào tạo'),
        'users': fields.one2many('res.users', 'session_id', string='Các sinh viên của khóa', readonly=True, domain=[('student', '=', True)]),
        'note': fields.text('Ghi chú'),
    }
    _order = 'seq'
    _sql_constraints = [
#        ('name_uniq', 'UNIQUE(name)', 'The name of an academic session must be unique!'),
    ]
    _defaults = {
        'seq': lambda *a: 10,
    }
aas_academic_session()

class aas_academic_plan(osv.osv):
    
    def check_existing(self, cr, uid, year_id, context=None):
        if year_id:
            existing = self.search(cr, uid, [('academic_year', '=', year_id), ('state', '=', 'confirmed')], context=context)
            if existing: raise osv.except_osv(_('Thông báo!'), _('Tồn tại kế hoạch đào tạo đã được duyệt cho năm học này!'))
        return True
    
    def default_academic_year(self, cr, uid, context=None):
        res = False
        year_obj = self.pool.get('aas.academic.year')
        current_academic_state = year_obj.get_current_academic_state(cr, uid, context=context)
        if current_academic_state[0]:
            res = current_academic_state[0].id
        return res
    
    _name = 'aas.academic.plan'
    _description= 'Kế hoạch đào tạo'
    _columns = {
        'name': fields.char('Tên kế hoạch đào tạo', size=128, required=True, readonly=True),
        'creator': fields.many2one('res.users', string='Người tạo', readonly=True),
        'validator': fields.many2one('res.users', string='Người duyệt', readonly=True),
        'academic_year': fields.many2one('aas.academic.year', string='Dùng cho năm học', required=True, readonly=True, states={'draft': [('readonly', False)]}),
        'state': fields.selection([('draft', _('Đang soạn thảo')), ('confirmed', _('Đã được duyệt'))], string='Trạng thái', readonly=True),
        'note': fields.text('Ghi chú', readonly=True, states={'draft':[('readonly', False)]}),
        'academic_plan_line': fields.one2many('aas.academic.plan.line', 'academic_plan', 'Chi tiết kế hoạch đào tạo', readonly=True, states={'draft':[('readonly', False)]}),
    }
    _defaults = {
        'name': lambda *a: '/',
        'state': lambda *a: 'draft',
        'creator': lambda self, cr, uid, context: uid,
        'academic_year': default_academic_year,
    }
    
    def create(self, cr, uid, vals, context=None):
        year_id = vals.get('academic_year', False)
        self.check_existing(cr, uid, year_id, context=context)
        return super(aas_academic_plan, self).create(cr, uid, vals, context=context)
    
    def write(self, cr, uid, ids, vals, context=None):
        year_id = vals.get('academic_year', False)
        for obj in self.browse(cr, uid, ids, context=context):
            if obj.academic_year.id != year_id:
                self.check_existing(cr, uid, year_id, context=context)
        return super(aas_academic_plan, self).write(cr, uid, ids, vals, context=context)
    
    def button_confirm(self, cr, uid, ids, context=None):
        for obj in self.browse(cr, uid, ids, context=context):
            self.check_existing(cr, uid, obj.academic_year.id, context=context)
        self.write(cr, uid, ids, {'state': 'confirmed', 'validator': uid})
        return True
    
    def button_cancel(self, cr, uid, ids, context=None):
        self.write(cr, uid, ids, {'state': 'draft', 'validator': False})
        return True
    
    
aas_academic_plan()

class aas_academic_week_state(osv.osv):
    _name = 'aas.academic.week.state'
    _description= 'Trạng thái tuần học'
    _columns = {
        'name': fields.char('Tên trạng thái tuần học', size=128, required=True),
        'code': fields.char('Mã trạng thái tuần học', size=128, required=True),
    }
    _sql_constraints = [
#        ('name_uniq', 'UNIQUE(name)', 'The name of an academic week state must be unique!'),
#        ('code_uniq', 'UNIQUE(code)', 'The code of an academic week state must be unique!'),
    ]
    
    def name_get(self, cr, uid, ids, context=None):
        res = []
        for state in self.browse(cr, uid, ids, context=context):
            res.append((state.id, state.name + ' (' + state.code + ')'))
        return res
    
aas_academic_week_state()

class aas_academic_plan_line(osv.osv):
    def is_in_current_academic_year(self, cr, uid, ids, field_name, arg, context=None):
        result = {}
        year_obj = self.pool.get('aas.academic.year')
        current_academic_state = year_obj.get_current_academic_state(cr, uid, context=context)
        for obj in self.browse(cr, uid, ids, context=context):
            result[obj.id] = False
            if current_academic_state[0] and current_academic_state[1]:
                if (obj.academic_year.id == current_academic_state[0].id):
                    result[obj.id] = True
        return result
    
    def default_academic_plan(self, cr, uid, context=False):
        if not context: context = {}
        res = context.get('plan_id', False)
        print res
        return res
    
    def check_existing(self, cr, uid, plan_id, session_id, week_id, context=None):
        if plan_id and session_id and week_id:
            existing = self.search(cr, uid, [('academic_plan', '=', plan_id), ('academic_session', '=', session_id), ('academic_week', '=', week_id)], context=context)
            if existing:
                week_obj = self.pool.get('aas.academic.week')
                session_obj = self.pool.get('aas.academic.session')
                week = week_obj.browse(cr, uid, week_id, context=context)
                session = session_obj.browse(cr, uid, session_id, context=context)
                raise osv.except_osv(_('Thông báo!'), _('Kế hoạch cho tuần %s của khóa %s đã tồn tại!') % (week.name, session.name))
        return True
    
    _name = 'aas.academic.plan.line'
    _description= 'Chi tiết kế hoạch đào tạo'
    _columns = {
        'academic_plan': fields.many2one('aas.academic.plan', string='Kế hoạch đào tạo', required=True),
        'academic_session': fields.many2one('aas.academic.session', string='Khóa', required=True),
        'academic_week': fields.many2one('aas.academic.week', string='Tuần học', required=True),
        'academic_week_state': fields.many2one('aas.academic.week.state', string='Trạng thái tuần học', required=True),
        'academic_year': fields.related('academic_plan', 'academic_year', type='many2one', relation='aas.academic.year', string='Năm học', readonly=True,
                                        store={'aas.academic.plan.line': (lambda self, cr, uid, ids, *a: ids, ['academic_plan'], 10),
                                               'aas.academic.plan': (lambda self, cr, uid, ids, *a: self.pool.get('aas.academic.plan.line').search(cr, uid, [('academic_plan', 'in', ids)]), ['academic_year'], 10)}),
        'date_start': fields.related('academic_week', 'date_start', string='Ngày bắt đầu', type='date'),
        'is_in_current_academic_year': fields.function(is_in_current_academic_year, method=True, type='boolean', 
                                                        store={'trobz.property': (lambda self, cr, uid, ids, *a: self.pool.get('aas.academic.plan.line').search(cr, uid, []), ['value'], 100),
                                                               'aas.academic.plan.line': (lambda self, cr, uid, ids, *a: ids, ['academic_plan', 'academic_year'], 100),
                                                               'aas.academic.plan': (lambda self, cr, uid, ids, *a: self.pool.get('aas.academic.plan.line').search(cr, uid, [('academic_plan', 'in', ids)]), ['academic_year'], 100)}),
    }
    _sql_constraints = [
#        ('plan_session_week_uniq', 'UNIQUE(academic_plan, academic_session, academic_week)', 'There should only be a state for a specific week and session of an academic plan!'),
    ]
    _defaults = {
        'academic_plan': default_academic_plan,
    }
    
    def create(self, cr, uid, vals, context=None):
        plan_id = vals.get('academic_plan', False)
        session_id = vals.get('academic_session', False)
        week_id = vals.get('academic_week', False)
        self.check_existing(cr, uid, plan_id, session_id, week_id, context=context)
        return super(aas_academic_plan_line, self).create(cr, uid, vals, context=context)
    
    def write(self, cr, uid, ids, vals, context=None):
        session_id = vals.get('academic_session', False)
        week_id = vals.get('academic_week', False)
        for obj in self.browse(cr, uid, ids, context=context):
            if obj.academic_session.id != session_id and obj.academic_week.id != week_id:
                self.check_existing(cr, uid, obj.academic_plan.id, session_id, week_id, context=context)
        return super(aas_academic_plan_line, self).write(cr, uid, ids, vals, context=context)
    
aas_academic_plan_line()


class aas_user(osv.osv):
    _inherit = 'res.users'
    _columns = {
        'degree_id': fields.many2one('aas.academic.degree', string='Bậc đào tạo'),
        'atype_id': fields.many2one('aas.academic.type', string='Loại hình đào tạo'),
        'session_id': fields.many2one('aas.academic.session', string='Khóa'),
        'titles': fields.many2many('aas.academic.title', 'aas_users_titles', 'user_id', 'title_id', 'Các học vị'),
        'ranks': fields.many2many('aas.academic.rank', 'aas_users_ranks', 'user_id', 'rank_id', 'Các học hàm'),
    }
aas_user()

# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
